#include "cilent.h"
#include <mysql/mysql.h>
#include <openssl/md5.h>
#define __BIG_FILE_SIZE__ (100*1024*1024) // 大文件边界



int recvn(int sockfd, void *buf, ssize_t length){
    char *p = (char *)buf;//char* 是因为偏移以1个字节为单位
    ssize_t cursize = 0;
    while(cursize < length){
        ssize_t sret = recv(sockfd,p+cursize,length-cursize,0);
        cursize += sret;
    }
    return cursize;
}


int sendn(int sockfd,void *buf,ssize_t length){
    char *p = (char *)buf;
    ssize_t cursize = 0;
    while(cursize < length){
        ssize_t sret = send(sockfd,p+cursize,length-cursize,0);
        cursize += sret;
    }
    return cursize;
}

int putsCommand(int sockfd,char *file_hash,char *filename){

    // 获取文件信息
    struct stat st;
    if(stat(filename,&st) == -1||S_ISDIR(st.st_mode)){
        printf("文件不存在或者是目录文件！\n");
        return -1;
    }

    // 发送文件信息

    // 发送文件名
    int ret = 0;
    int namelen = strlen(filename);
    ret = sendn(sockfd,&namelen,sizeof(namelen));
    printf("ret = %d\n",ret);
    ret = sendn(sockfd,filename,namelen);
    printf("ret = %d\n",ret);

    // 发送哈希值
    int hash_len = strlen(file_hash);
    ret = sendn(sockfd,&hash_len,sizeof(hash_len));
    printf("ret = %d\n",ret);
    ret = sendn(sockfd,file_hash,hash_len);
    printf("ret = %d\n",ret);

    // 发送文件大小
    unsigned long filesize = st.st_size;
    ret = sendn(sockfd,&filesize,sizeof(filesize));
    printf("ret = %d\n",ret);

    // 接收服务端查询结果
    int server_query_result = 0;
    ret = recvn(sockfd,&server_query_result,sizeof(server_query_result));
    printf("ret = %d\n",ret);
    if(server_query_result == -1) {
        printf("服务端查询失败!\n");
        return -1;
    }

    // 接收服务端极速上传响应
    int fast_upload_response = 0;
    recvn(sockfd,&fast_upload_response,sizeof(fast_upload_response));

    if(fast_upload_response == 1){
        // 可以极速上传
        printf("可以进行极速上传！\n");
        int insert_result= 1;
        recvn(sockfd,&insert_result,sizeof(insert_result));
        printf("insert_result = %d\n",insert_result);
        return 0;
    }else if(fast_upload_response == -1){
        printf("服务端上传失败！\n");
        return -1;
    }


    // 正常上传

    // 接收服务端当前文件大小，即偏移量
    unsigned long offset = 0;
    recvn(sockfd,&offset,sizeof(offset));

    // 打开文件，准备进行传输
    int filefd = open(filename,O_RDONLY);
    if(filefd == -1){
        printf("无法打开文件\n");
        return -1;
    }
    lseek(filefd,offset,SEEK_SET);


    // 文件内容传输
    unsigned long sent = offset;

    if(filesize > __BIG_FILE_SIZE__){
        // 大文件传输
        char send_buf[4096] = {0};
        while(sent < filesize){
            int sendsize = (filesize - sent > sizeof(send_buf))?sizeof(send_buf):(filesize - sent);
            ret = read(filefd,send_buf,sendsize);
            if(ret == 0) break;

            sendn(sockfd,send_buf,ret);
            sent +=ret;
            printf("发送进度：%5.2f%%\r",100.00*sent / filesize);
            fflush(stdout);
        }
    }else{
        // 小文件传输
        char send_buf[1024];
        while(sent < filesize){
            int sendsize = (filesize - sent > sizeof(send_buf))?sizeof(send_buf):(filesize - sent);
            ret = read(filefd,send_buf,sendsize);
            if(ret == 0) break;

            int len = ret;
            sendn(sockfd,&len,sizeof(len));
            sendn(sockfd,send_buf,len);

            sent += len;
            printf("发送进度：%5.2f%%\r",100.0 *sent / filesize);
            fflush(stdout);
        }
    }

    close(filefd);
    printf("文件发送完成，文件总字节大小：%lu\n",sent);
    return 0;
}
